﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraGrid.Columns;
using ProgNetComponentsDx.Browsers;
using ProgNetComponents.Classes;
using System.Diagnostics;
using WindowsInput;
using ProgNetComponentsDx.Options;
using System.Threading;

namespace BuildHelper.Setup.BazyDanych
{
    public partial class FormBazyDanych : MyBaseSqlCeGridForm
    {
        public static FormBazyDanych Instance
        {
            get;
            private set;
        }
        public FormBazyDanych()
        {
            InitializeComponent();
            Instance = this;
        }
        
        #region fields
        private List<string> found = new List<string>();
        private List<string> notfound = new List<string>();
        private object lockDataSet = new object();
        private object lockProgress = new object();

        private System.Data.OracleClient.OracleConnection _Connection = null;
        private System.Data.OracleClient.OracleConnection Connection
        {
            get
            {
                if (_Connection == null)
                    _Connection = new System.Data.OracleClient.OracleConnection();
                return _Connection;
            }
        }
        private int progress;
        private int max;
        private bool showMsg = false;
        #endregion

        protected override void OnLoad()
        {
            if (!this.IsDesignMode())
            {
                rep_colSprawdz.Buttons[0].Image = this.commonImageCollectionFull1.Images[83].ResizeImage(18, 18);
                rep_colOtworz.Buttons[0].Image = this.commonImageCollectionFull1.Images[14].ResizeImage(18, 18);
                rep_colOdswiez.Buttons[0].Image = this.commonImageCollectionFull1.Images[86].ResizeImage(18, 18);
            }
            base.OnLoad();
        }
        protected override void OnClosed(EventArgs e)
        {
            Instance = null;
            base.OnClosed(e);
        }
        protected override bool Save()
        {
            DataRow[] rows = bazyDanychDataSet.STP_BAZY_DANYCH.Select("STP_BD_WLASNA = 1", null, DataViewRowState.ModifiedCurrent | DataViewRowState.Added);
            if (rows != null)
                foreach (DataRow r in rows)
                {
                    r["STP_BD_DATA_AKTUALIZACJI"] = DateTime.Now;
                }

            return base.Save();
        }
        private void rep_colSprawdz_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            FinishEdit();
            DataRow r = gvMain.GetFocusedDataRow();
            if (r.CanRead())
                if (testConnection(r))
                    this.ShowDxInfoDialog("Połączenie udane.");
                else
                    this.ShowDxErrorDialog("Połączenie nie udane!");
        }
        private void rep_colOtworz_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            DataRow r = gvMain.GetFocusedDataRow();
            Tools.OpenDB(r);
        }
        private void bbiSzukaj_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            Browser b = browserProvider1.GetBrowser(Init.InitFormBrowserNames.Setup.SrodowiskaPredefiniowane);
            if (b != null)
            {
                if (!backgroundControl.IsRunning)
                {
                    DataRow[] rows = b.GetTable().Select();
                    List<DataRow> envsRows = new List<DataRow>();
                    bool updateOnlyActive = OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.UaktualniajTylkoDzialajace);

                    foreach (DataRow r in rows)
                    {
                        if (!updateOnlyActive || r["STP_SR_DZIALA"].AsBool())
                        {
                            envsRows.Add(r);
                        }
                    }
                    
                    showMsg = true;
                    found.Clear();
                    notfound.Clear();
                    backgroundControl.LabelText = "Szukanie Baz Danych";
                    backgroundControl.ProgressType = ProgNetComponentsDx.Forms.ProgressType.Percentage;
                    backgroundControl.ClearActions();
                    max = envsRows.Count;
                    progress = 0;
                    backgroundControl.SupportCancelation = true;
                    backgroundControl.MaxProgress = max;
                    backgroundControl.Progress = 0;
                    List<string> list = new List<string>();
                    int minCount = 0;
                    int maxThreads = OptionCache.GetOptionValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.MaxThreads).AsInt(1);
                    minCount = max / maxThreads;
                    int rest = max % maxThreads;
                    if (rest > 0)
                        minCount++;

                    foreach (DataRow r in envsRows)
                    {
                        list.Add(r["STP_SR_NAZWA"].AsString());
                        if (list.Count >= minCount)
                        {
                            backgroundControl.AddAction(new Action<List<string>>(SzukajBazy), new object[] { list });
                            list = new List<string>();
                        }
                    }
                    if (list.Count > 0)
                    {
                        backgroundControl.AddAction(new Action<List<string>>(SzukajBazy), new object[] { list });
                    }
                    Tools.ClearInvalidHosts();
                    backgroundControl.Start();
                }
                else
                {
                    this.ShowDxInfoDialog("Operacja w toku.");
                }
            }
        }

        private void bbiDodajBazeZeSrodowiska_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!backgroundControl.IsRunning)
            {
                Browser b = browserProvider1.GetBrowser(Init.InitFormBrowserNames.Setup.SrodowiskaPredefiniowane);

                if (b != null)
                {
                    ObjectDialogResult dlg = b.ShowDialog();
                    if (dlg.DialogResult == DialogResult.OK)
                    {
                        string env = b.GetDisplayForValue(dlg.Value).AsString();
                        found.Clear();
                        notfound.Clear();
                        showMsg = true;
                        backgroundControl.ClearActions();
                        backgroundControl.LabelText = "Szukanie Bazy Danych";
                        backgroundControl.ProgressType = ProgNetComponentsDx.Forms.ProgressType.Merque;
                        backgroundControl.AddAction(new Action<string, bool>(SzukajBazy), new object[] { env, OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.RefreshEnvWithDb) });
                        backgroundControl.Start();
                    }
                }
            }
            else
            {
                this.ShowDxInfoDialog("Operacja w toku.");
            }
        }
        private void bbiSprawdzWersje_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            DataRow[] rows = this.bazyDanychDataSet.STP_BAZY_DANYCH.Select("STP_BD_WLASNA = 0");
            if (!backgroundControl.IsRunning)
            {
                showMsg = false;
                backgroundControl.LabelText = "Szukanie Bazy Danych";
                backgroundControl.ProgressType = ProgNetComponentsDx.Forms.ProgressType.Percentage;
                max = rows.Length;
                backgroundControl.MaxProgress = max;
                progress = 0;
                backgroundControl.SupportCancelation = true;
                backgroundControl.ClearActions();
                List<string> list = new List<string>();
                foreach (DataRow r in rows)
                {
                    list.Add(r["STP_BD_NAZWA"].AsString());
                    if (list.Count == 10)
                    {
                        backgroundControl.AddAction(new Action<List<string>>(SzukajBazy), new object[] { list });
                        list = new List<string>();
                    }
                } if (list.Count > 0)
                {
                    backgroundControl.AddAction(new Action<List<string>>(SzukajBazy), new object[] { list });
                }
                backgroundControl.Start();
            }
            else
            {
                this.ShowDxInfoDialog("Operacja w toku.");
            }
        }

        private bool testConnection(DataRow r)
        {
            bool result = true;
            if (r.CanRead())
            {
                try
                {
                    string host = r["STP_BD_HOST"].AsString();
                    string sid = r["STP_BD_SID"].AsString();
                    string service = r["STP_BD_SERVICE"].AsString();
                    string port = r["STP_BD_PORT"].AsString();
                    string user = r["STP_BD_USER"].AsString();
                    string pass = r["STP_BD_PASS"].AsString();

                    Connection.ConnectionString = "Data Source=(DESCRIPTION=(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = " + host +
                        ")(PORT = " + port + ")))(CONNECT_DATA = (SERVER=DEDICATED)(" +
                        (service.IsNotNull() ? ("SERVICE_NAME = " + service) :
                        ("SID = " + sid)) +
                        ")));User Id=" + user + ";Password=" + pass + ";";
                    Connection.Open();
                    Connection.Close();
                }
                catch
                {
                    result = false;
                    string path = Environment.GetEnvironmentVariable("Path").AsString();
                    string oracleHome = Environment.GetEnvironmentVariable("ORACLE_HOME").AsString();
                    
                    if (oracleHome.IsNull())
                    {
                        this.ShowDxInfoDialog("Brak zmiennej środowiskowej ORACLE_HOME.");
                    }
                    else
                    {
                        if (!path.ToUpper().Contains(oracleHome.ToUpper()))
                        {
                            if (this.ShowDxYNQuestionDialog("Zmienna Path nie ma odwołania do ORACLE_HOME. Czy chcesz dodać ORACLE_HOME do Path?") == System.Windows.Forms.DialogResult.Yes)
                            {
                                string value = path + ";" + oracleHome + ";" + oracleHome + "\\bin";
                                GlobalTools.ProcessTools.SetEnvVariable(Process.GetCurrentProcess(), "Path", value);
                                Environment.SetEnvironmentVariable("Path", value, EnvironmentVariableTarget.Process);
                                Process cmd = GlobalTools.CreateCMDProcess(null);
                                if (value.XMatch("\\s+"))
                                    value = value.AddDoubleQuotes();
                                cmd.Execute("setx /m Path " + value);
                                cmd.CallExit();
                                cmd.WaitForExit();
                                try
                                {
                                    cmd.KillProcessTree();
                                    cmd.Dispose();
                                }
                                catch { }
                                cmd = null;
                                try
                                {
                                    Connection.Open();
                                    Connection.Close();
                                    result = true;
                                }
                                catch { }
                            }
                        }
                    }

                    
                }
            }
            return result;
        }

        private void modeProvider1_CustomGetModes(object sender, ProgNetComponentsDx.Mode.CustomModeSettingsEventArgs e)
        {
            if (sender is GridColumn && e.Row != null && !e.Row["STP_BD_WLASNA"].AsBool())
            {
                if (sender != colSprawdz)
                    e.IsReadOnly = true;
            }
        }

        private void backgroundForm_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (showMsg)
            {
                string found = this.found.AsString();
                string notfound = this.notfound.AsString();
                string str = "";
                if (found.IsNotNull())
                    str += "Znalezione bazy:\n\r" + found;
                if (notfound.IsNotNull())
                {
                    str = str.AppendLine("");
                    str = str.AppendLine("Nie znaleziono baz dla środowisk:\n\r" + notfound);
                }
                if (str.IsNull())
                    str = "Nie znaleziono baz danych.";
                this.ShowDxInfoDialog(str);
            }
        }

        
        private void SzukajBazy(List<string> envs)
        {
            foreach (string env in envs)
            {
                if (backgroundControl.IsCanceling)
                    return;
                SzukajBazy(env);
            }
        }
        private void SzukajBazy(string env)
        {
            SzukajBazy(env, false);
        }
        private void SzukajBazy(string env, bool refreshEnv)
        {
            Tools.DbData d = Tools.GetDbData(env, refreshEnv);
            if (backgroundControl.ProgressType == ProgNetComponentsDx.Forms.ProgressType.Percentage)
            {
                lock (lockProgress)
                {
                    progress++;
                    backgroundControl.Label2Text = progress + "/" + max;
                    backgroundControl.Progress = progress;
                }
            }

            if (d != null && d.Host.IsNotNull())
            {
                lock (lockDataSet)
                {
                    found.Add(env);
                    MergeRow(d);
                }
            }
            else
            {
                lock (lockDataSet)
                {
                    notfound.Add(env);
                    if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.KasujNieistniejace))
                        DeleteEnv(env);
                }
            }
        }

        public void DeleteEnv(string env)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(DeleteEnv), env);
                return;
            }
            DataRow r;
            r = this.bazyDanychDataSet.STP_BAZY_DANYCH.SelectFirstRow("STP_BD_NAZWA = " + env.EscapeSql());
            if (r != null)
            {
                r.Delete();
                if (modeProvider1.CurrentMode != ProgNetComponentsDx.Enums.FormMode.Edit)
                    modeProvider1.CurrentMode = ProgNetComponentsDx.Enums.FormMode.Edit;
                changeDetectorProvider1.SetModified();
            }
        }
        public void MergeRow(Tools.DbData d)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<Tools.DbData>(MergeRow), d);
                return;
            }
            bool modified = false;
            DataRow r;
            r = this.bazyDanychDataSet.STP_BAZY_DANYCH.SelectFirstRow("STP_BD_NAZWA = " + d.EnvName.EscapeSql());

            if (r == null)
            {
                if (modeProvider1.CurrentMode != ProgNetComponentsDx.Enums.FormMode.Edit)
                    modeProvider1.CurrentMode = ProgNetComponentsDx.Enums.FormMode.Edit;
                r = this.bazyDanychDataSet.STP_BAZY_DANYCH.NewRow();
                r["STP_BD_NAZWA"] = d.EnvName;
                bazyDanychDataSet.STP_BAZY_DANYCH.Rows.Add(r);
            }
            modified |= r.SetColVal("STP_BD_USER", d.UserName);
            modified |= r.SetColVal("STP_BD_PORT", d.Port);
            modified |= r.SetColVal("STP_BD_PASS", d.Pass);
            modified |= r.SetColVal("STP_BD_SERVICE", d.Service);
            modified |= r.SetColVal("STP_BD_SID", d.Sid);
            modified |= r.SetColVal("STP_BD_HOST", d.Host);
            modified |= r.SetColVal("STP_BD_WERSJA", d.Wersja);
            modified |= r.SetColVal("STP_BD_WLASNA", false);
            modified |= r.SetColVal("STP_BD_DATA_AKTUALIZACJI", DateTime.Now);
            if (r.RowState != DataRowState.Added && modified)
            {
                if (modeProvider1.CurrentMode != ProgNetComponentsDx.Enums.FormMode.Edit)
                    modeProvider1.CurrentMode = ProgNetComponentsDx.Enums.FormMode.Edit;
                changeDetectorProvider1.SetModified();
            }
        }

        private void rep_colOdswiez_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            if (!backgroundControl.IsRunning)
            {
                FinishEdit();
                DataRow r = gvMain.GetFocusedDataRow();
                if (r != null)
                {
                    if (r["STP_BD_WLASNA"].AsBool())
                        return;
                    string env = r["STP_BD_NAZWA"].AsString();
                    found.Clear();
                    notfound.Clear();
                    showMsg = true;
                    backgroundControl.ClearActions();
                    backgroundControl.LabelText = "Odświeżanie Bazy Danych";
                    backgroundControl.ProgressType = ProgNetComponentsDx.Forms.ProgressType.Merque;
                    backgroundControl.AddAction(new Action<string, bool>(SzukajBazy), new object[] { env, OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.RefreshEnvWithDb) });
                    backgroundControl.Start();
                }
            }
            else
            {
                this.ShowDxInfoDialog("Operacja w toku.");
            }
        }

        private void bbiDodajBaze_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            DataRow r = gvMain.GetFocusedDataRow();
            if (r != null)
            {
                if (GlobalTools.DBTools.AddTns(r))
                {
                    this.ShowDxInfoDialog("Baza dodana.");
                }
            }
        }

        private void bbiDodajWszystkie_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (GlobalTools.DBTools.AddTns(this.bazyDanychDataSet.STP_BAZY_DANYCH))
            {
                this.ShowDxInfoDialog("Bazy dodane.");
            }
        }

        private void barManager1_LayoutUpgrade(object sender, DevExpress.Utils.LayoutUpgadeEventArgs e)
        {
            if (e.PreviousVersion.AsInt() < 2)
            {
                bar1.ItemLinks.Add(bsiTnsNamesOra, true);
            }
        }

    }
}
